<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>文件上传与下载和登录 | 浪飞IT小栈</title>
    <meta name="generator" content="VuePress 1.9.9">
    <link rel="icon" href="/img/favicon.ico">
    <meta name="description" content="前后端技术分享">
    <meta name="keywords" content="前端博客,后端博客,人工智能,个人技术博客,前端,前端开发,前端框架,web前端,前端面试题,技术文档,学习,面试,JavaScript,js,ES6,TypeScript,vue,python,css3,html5,Node,git,github,markdown,java,Spring,Springboot,Redis,mysql">
    <meta name="baidu-site-verification" content="7F55weZDDc">
    <meta name="theme-color" content="#11a8cd">
    
    <link rel="preload" href="/assets/css/0.styles.ada71c49.css" as="style"><link rel="preload" href="/assets/js/app.a2a00aa5.js" as="script"><link rel="preload" href="/assets/js/2.256f807a.js" as="script"><link rel="preload" href="/assets/js/44.7c7cb8a9.js" as="script"><link rel="prefetch" href="/assets/js/10.ab144fe3.js"><link rel="prefetch" href="/assets/js/11.062e0879.js"><link rel="prefetch" href="/assets/js/12.f9c60882.js"><link rel="prefetch" href="/assets/js/13.0a6ebfcf.js"><link rel="prefetch" href="/assets/js/14.03fc6f12.js"><link rel="prefetch" href="/assets/js/15.19dbf9fd.js"><link rel="prefetch" href="/assets/js/16.6e68160b.js"><link rel="prefetch" href="/assets/js/17.1d678834.js"><link rel="prefetch" href="/assets/js/18.4536fd5c.js"><link rel="prefetch" href="/assets/js/19.9c1b65df.js"><link rel="prefetch" href="/assets/js/20.c5f96e71.js"><link rel="prefetch" href="/assets/js/21.3f0b334e.js"><link rel="prefetch" href="/assets/js/22.55c868be.js"><link rel="prefetch" href="/assets/js/23.91286241.js"><link rel="prefetch" href="/assets/js/24.c1af1909.js"><link rel="prefetch" href="/assets/js/25.a995a755.js"><link rel="prefetch" href="/assets/js/26.abc5dea3.js"><link rel="prefetch" href="/assets/js/27.1eb62850.js"><link rel="prefetch" href="/assets/js/28.b383a871.js"><link rel="prefetch" href="/assets/js/29.088e0d73.js"><link rel="prefetch" href="/assets/js/3.cd716564.js"><link rel="prefetch" href="/assets/js/30.3ccc98d5.js"><link rel="prefetch" href="/assets/js/31.aab7cc23.js"><link rel="prefetch" href="/assets/js/32.5e16b7e6.js"><link rel="prefetch" href="/assets/js/33.4aaeb741.js"><link rel="prefetch" href="/assets/js/34.45e8e898.js"><link rel="prefetch" href="/assets/js/35.5899c97a.js"><link rel="prefetch" href="/assets/js/36.32e2e263.js"><link rel="prefetch" href="/assets/js/37.c4e27bbd.js"><link rel="prefetch" href="/assets/js/38.fe5e60d2.js"><link rel="prefetch" href="/assets/js/39.2cb0b4ee.js"><link rel="prefetch" href="/assets/js/4.edf4d5e7.js"><link rel="prefetch" href="/assets/js/40.08d5bead.js"><link rel="prefetch" href="/assets/js/41.2f80f24b.js"><link rel="prefetch" href="/assets/js/42.43a49913.js"><link rel="prefetch" href="/assets/js/43.08da7ec2.js"><link rel="prefetch" href="/assets/js/45.0ddf7e7f.js"><link rel="prefetch" href="/assets/js/46.7c4609a5.js"><link rel="prefetch" href="/assets/js/47.edf3ddf8.js"><link rel="prefetch" href="/assets/js/48.569a90b9.js"><link rel="prefetch" href="/assets/js/49.fa368ac8.js"><link rel="prefetch" href="/assets/js/5.24054156.js"><link rel="prefetch" href="/assets/js/50.b9b3ea7f.js"><link rel="prefetch" href="/assets/js/51.a2ebf0fe.js"><link rel="prefetch" href="/assets/js/52.31f02238.js"><link rel="prefetch" href="/assets/js/53.4110ef1e.js"><link rel="prefetch" href="/assets/js/54.dab741c7.js"><link rel="prefetch" href="/assets/js/55.f27984e9.js"><link rel="prefetch" href="/assets/js/56.bd4c1a8e.js"><link rel="prefetch" href="/assets/js/57.375d40cb.js"><link rel="prefetch" href="/assets/js/58.932e3864.js"><link rel="prefetch" href="/assets/js/59.e657be1b.js"><link rel="prefetch" href="/assets/js/6.b259c061.js"><link rel="prefetch" href="/assets/js/60.88d94274.js"><link rel="prefetch" href="/assets/js/61.fa71d884.js"><link rel="prefetch" href="/assets/js/62.a9d3b3b7.js"><link rel="prefetch" href="/assets/js/63.f849fe75.js"><link rel="prefetch" href="/assets/js/64.1770f7a9.js"><link rel="prefetch" href="/assets/js/65.6afc33db.js"><link rel="prefetch" href="/assets/js/66.799f2eb4.js"><link rel="prefetch" href="/assets/js/67.f36b2f7d.js"><link rel="prefetch" href="/assets/js/68.868cd00b.js"><link rel="prefetch" href="/assets/js/69.4c29b907.js"><link rel="prefetch" href="/assets/js/7.e34ea00f.js"><link rel="prefetch" href="/assets/js/70.1b993ed4.js"><link rel="prefetch" href="/assets/js/71.e16ad4f9.js"><link rel="prefetch" href="/assets/js/72.627505e6.js"><link rel="prefetch" href="/assets/js/73.32768e14.js"><link rel="prefetch" href="/assets/js/74.968a580d.js"><link rel="prefetch" href="/assets/js/75.42d5af3d.js"><link rel="prefetch" href="/assets/js/76.19a69d31.js"><link rel="prefetch" href="/assets/js/77.cf627a78.js"><link rel="prefetch" href="/assets/js/78.07177880.js"><link rel="prefetch" href="/assets/js/8.c4dd00ce.js"><link rel="prefetch" href="/assets/js/9.0ff73be2.js">
    <link rel="stylesheet" href="/assets/css/0.styles.ada71c49.css">
  </head>
  <body class="theme-mode-light">
    <div id="app" data-server-rendered="true"><div class="theme-container sidebar-open have-rightmenu"><header class="navbar blur"><div title="目录" class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/img/logo.png" alt="浪飞IT小栈" class="logo"> <span class="site-name can-hide">浪飞IT小栈</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link">首页</a></div><div class="nav-item"><a href="/pages/6138ae/" class="nav-link">Java速通</a></div><div class="nav-item"><a href="/pages/705b35/" class="nav-link">面试经典</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="精品项目" class="dropdown-title"><a href="/project/" class="link-title">精品项目</a> <span class="title" style="display:none;">精品项目</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>桌面端</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/pages/8143cc480faf9a11/" class="nav-link">JavaScript</a></li></ul></li><li class="dropdown-item"><h4>PC后端</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/note/javascript/" class="nav-link">项目1</a></li><li class="dropdown-subitem"><a href="/note/typescript-axios/" class="nav-link">项目二</a></li></ul></li></ul></div></div><div class="nav-item"><a href="/about/" class="nav-link">电子书</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="索引" class="dropdown-title"><a href="/archives/" class="link-title">索引</a> <span class="title" style="display:none;">索引</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/" class="nav-link">分类</a></li><li class="dropdown-item"><!----> <a href="/tags/" class="nav-link">标签</a></li><li class="dropdown-item"><!----> <a href="/archives/" class="nav-link">归档</a></li></ul></div></div><div class="nav-item"><a href="/pages/0c07b2/" class="nav-link">IT杂货铺</a></div><div class="nav-item"><a href="/archives/" class="nav-link">更多资源</a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <div class="sidebar-hover-trigger"></div> <aside class="sidebar" style="display:none;"><div class="blogger"><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/avatar.jpg"> <div class="blogger-info"><h3>浪飞yes</h3> <span>无法简单的人儿~</span></div></div> <nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link">首页</a></div><div class="nav-item"><a href="/pages/6138ae/" class="nav-link">Java速通</a></div><div class="nav-item"><a href="/pages/705b35/" class="nav-link">面试经典</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="精品项目" class="dropdown-title"><a href="/project/" class="link-title">精品项目</a> <span class="title" style="display:none;">精品项目</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>桌面端</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/pages/8143cc480faf9a11/" class="nav-link">JavaScript</a></li></ul></li><li class="dropdown-item"><h4>PC后端</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/note/javascript/" class="nav-link">项目1</a></li><li class="dropdown-subitem"><a href="/note/typescript-axios/" class="nav-link">项目二</a></li></ul></li></ul></div></div><div class="nav-item"><a href="/about/" class="nav-link">电子书</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="索引" class="dropdown-title"><a href="/archives/" class="link-title">索引</a> <span class="title" style="display:none;">索引</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/" class="nav-link">分类</a></li><li class="dropdown-item"><!----> <a href="/tags/" class="nav-link">标签</a></li><li class="dropdown-item"><!----> <a href="/archives/" class="nav-link">归档</a></li></ul></div></div><div class="nav-item"><a href="/pages/0c07b2/" class="nav-link">IT杂货铺</a></div><div class="nav-item"><a href="/archives/" class="nav-link">更多资源</a></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>开篇</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>基础语法</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>面向对象</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>常用类</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>基础高级</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>数据库</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>前端技术</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/pages/84c5d2/" class="sidebar-link">HTML与CSS</a></li><li><a href="/pages/42b6b6/" class="sidebar-link">JavaScript与DOM</a></li><li><a href="/pages/1125b7/" class="sidebar-link">网络编程与Tomcat</a></li><li><a href="/pages/be0e03/" class="sidebar-link">Http与Servlet</a></li><li><a href="/pages/9902e4/" class="sidebar-link">请求与响应</a></li><li><a href="/pages/18345f/" class="sidebar-link">JSP与EL与JSTL</a></li><li><a href="/pages/aa67fd/" class="sidebar-link">WEB版CRUD</a></li><li><a href="/pages/baec2f/" class="sidebar-link">Cookie与Session</a></li><li><a href="/pages/73e2cb/" aria-current="page" class="active sidebar-link">文件上传与下载和登录</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level2"><a href="/pages/73e2cb/#一、今天学习内容与目标" class="sidebar-link">一、今天学习内容与目标</a></li><li class="sidebar-sub-header level2"><a href="/pages/73e2cb/#二、文件上传" class="sidebar-link">二、文件上传</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_2-1-项目准备" class="sidebar-link">2.1 项目准备</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_2-2-编写-register-jsp" class="sidebar-link">2.2 编写 register.jsp</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_2-3-编写-fileuploadservlet-java" class="sidebar-link">2.3 编写 FileUploadServlet.java</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_2-4-查看请求数据及问题" class="sidebar-link">2.4 查看请求数据及问题</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_2-5-servlet-3-0-文件上传" class="sidebar-link">2.5 Servlet 3.0 文件上传</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_2-5-1-api" class="sidebar-link">2.5.1 API</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_2-5-2-代码示例" class="sidebar-link">2.5.2 代码示例</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_2-6-文件上传细节" class="sidebar-link">2.6 文件上传细节</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_2-6-1-获取上传文件名" class="sidebar-link">2.6.1 获取上传文件名</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_2-6-2-文件名相同覆盖现有文件-掌握" class="sidebar-link">2.6.2 文件名相同覆盖现有文件(掌握)</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_2-6-3-文件保存位置问题" class="sidebar-link">2.6.3 文件保存位置问题</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_2-6-4-无法获取项目下的-upload-目录" class="sidebar-link">2.6.4 无法获取项目下的 upload 目录</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_2-7-文件类型约束问题-掌握" class="sidebar-link">2.7 文件类型约束问题(掌握)</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_2-7-1-修改-uploadservlet-java" class="sidebar-link">2.7.1 修改 UploadServlet.java</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_2-7-2-修改-register-jsp" class="sidebar-link">2.7.2 修改 register.jsp</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_2-8-文件大小约束问题" class="sidebar-link">2.8 文件大小约束问题</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_2-8-1-修改-register-jsp" class="sidebar-link">2.8.1 修改 register.jsp</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_2-8-2-修改-fileuploadservlet-java" class="sidebar-link">2.8.2 修改 FileUploadServlet.java</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/73e2cb/#三、文件下载" class="sidebar-link">三、文件下载</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_3-1-文件下载简单实现" class="sidebar-link">3.1 文件下载简单实现</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_3-1-1-在项目提供下载资源" class="sidebar-link">3.1.1 在项目提供下载资源</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_3-1-2-编写-download-jsp" class="sidebar-link">3.1.2 编写 download.jsp</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_3-2-文件下载限制-掌握" class="sidebar-link">3.2 文件下载限制(掌握)</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_3-2-1-移动下载资源到-web-inf-下" class="sidebar-link">3.2.1 移动下载资源到 WEB-INF 下</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_3-2-2-修改-download-jsp" class="sidebar-link">3.2.2 修改 download.jsp</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_3-2-3-编写-downloadservlet-java" class="sidebar-link">3.2.3 编写 DownloadServlet.java</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_3-3-下载文件名称问题-能使用即可" class="sidebar-link">3.3 下载文件名称问题（能使用即可）</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/73e2cb/#四、登录实现-掌握" class="sidebar-link">四、登录实现(掌握)</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_4-1-为什么做登录" class="sidebar-link">4.1 为什么做登录</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_4-2-分析登录流程" class="sidebar-link">4.2 分析登录流程</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_4-3-登录实现" class="sidebar-link">4.3 登录实现</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-3-1-项目准备及新建-user-表" class="sidebar-link">4.3.1 项目准备及新建 user 表</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-3-2-编写-user-java" class="sidebar-link">4.3.2 编写 User.java</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-3-3-编写-usermapper-xml" class="sidebar-link">4.3.3 编写 UserMapper.xml</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-3-4-编写-iuserdao-java-和-userdaoimpl-java" class="sidebar-link">4.3.4 编写 IUserDAO.java 和 UserDAOImpl.java</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-3-5-编写-loginservlet-java" class="sidebar-link">4.3.5 编写 LoginServlet.java</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-3-6-编写-login-jsp" class="sidebar-link">4.3.6 编写 login.jsp</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_4-4-访问限制" class="sidebar-link">4.4 访问限制</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-4-1-修改-loginservlet-java" class="sidebar-link">4.4.1 修改 LoginServlet.java</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-4-2-修改-productservlet-的-service-方法" class="sidebar-link">4.4.2 修改 ProductServlet 的 service 方法</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_4-5-登录实现异常提示" class="sidebar-link">4.5 登录实现异常提示</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-5-1-修改-usermapper-xml" class="sidebar-link">4.5.1 修改 UserMapper.xml</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-5-2-修改-iuserdao-java-和-userdaoimpl-java" class="sidebar-link">4.5.2 修改 IUserDAO.java 和 UserDAOImpl.java</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-5-3-修改-loginservlet-java" class="sidebar-link">4.5.3 修改 LoginServlet.java</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_4-5-4-存在的问题" class="sidebar-link">4.5.4 存在的问题</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/73e2cb/#五、登录加入业务层-掌握" class="sidebar-link">五、登录加入业务层(掌握)</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_5-1-三层架构介绍" class="sidebar-link">5.1 三层架构介绍</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_5-2-业务层命名规范-掌握" class="sidebar-link">5.2 业务层命名规范(掌握)</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_5-3-编写-iuserservice-java-和-userserviceimpl-java" class="sidebar-link">5.3 编写 IUserService.java 和 UserServiceImpl.java</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_5-4-修改-loginservlet-java" class="sidebar-link">5.4 修改 LoginServlet.java</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/73e2cb/#六、加入用户头像-拓展" class="sidebar-link">六、加入用户头像(拓展)</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_6-1-显示用户头像" class="sidebar-link">6.1 显示用户头像</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_6-1-1-新建存放头像文件夹" class="sidebar-link">6.1.1 新建存放头像文件夹</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_6-1-2-修改-user-表" class="sidebar-link">6.1.2 修改 user 表</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_6-1-3-修改-user-java" class="sidebar-link">6.1.3 修改 User.java</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_6-1-4-修-list-jsp" class="sidebar-link">6.1.4 修 list.jsp</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_6-2-修改用户头像" class="sidebar-link">6.2 修改用户头像</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_6-2-1-修改-list-jsp" class="sidebar-link">6.2.1 修改 list.jsp</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_6-2-2-编写-replaceimg-jsp" class="sidebar-link">6.2.2 编写 replaceImg.jsp</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_6-2-3-编写-headimgservlet-java" class="sidebar-link">6.2.3 编写 HeadImgServlet.java</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_6-2-4-修改-iuserservice-java-和-userserviceimpl-java" class="sidebar-link">6.2.4 修改 IUserService.java 和 UserServiceImpl.java</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_6-2-5-修改-iuserdao-java-和-userdaoimpl-java" class="sidebar-link">6.2.5 修改 IUserDAO.java 和 UserDAOImpl.java</a></li><li class="sidebar-sub-header level4"><a href="/pages/73e2cb/#_6-2-6-修改-usermapper-xml" class="sidebar-link">6.2.6 修改 UserMapper.xml</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/73e2cb/#七、小结也作业" class="sidebar-link">七、小结也作业</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_7-1-小结" class="sidebar-link">7.1 小结</a></li><li class="sidebar-sub-header level3"><a href="/pages/73e2cb/#_7-2-作业" class="sidebar-link">7.2 作业</a></li></ul></li></ul></li><li><a href="/pages/f99e33/" class="sidebar-link">项目实战-MIS系统</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>热门框架</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>前后端分离</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>权限控制</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>NoSQL</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>微服务</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>消息中间件</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>脚手架</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>技术增值</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <div><main class="page"><div class="theme-vdoing-wrapper "><div class="articleInfo-wrap" data-v-06225672><div class="articleInfo" data-v-06225672><ul class="breadcrumbs" data-v-06225672><li data-v-06225672><a href="/" title="首页" class="iconfont icon-home router-link-active" data-v-06225672></a></li> <li data-v-06225672><a href="/categories/?category=Java%E9%80%9F%E9%80%9A" title="分类" data-v-06225672>Java速通</a></li><li data-v-06225672><a href="/categories/?category=%E5%89%8D%E7%AB%AF%E6%8A%80%E6%9C%AF" title="分类" data-v-06225672>前端技术</a></li></ul> <div class="info" data-v-06225672><div title="作者" class="author iconfont icon-touxiang" data-v-06225672><a href="https://github.com/langfeiyes" target="_blank" title="作者" class="beLink" data-v-06225672>langfeiyes</a></div> <div title="创建时间" class="date iconfont icon-riqi" data-v-06225672><a href="javascript:;" data-v-06225672>2024-03-03</a></div> <!----></div></div></div> <!----> <div class="content-wrapper"><div class="right-menu-wrapper"><div class="right-menu-margin"><div class="right-menu-title">目录</div> <div class="right-menu-content"></div></div></div> <h1><img src="">文件上传与下载和登录<!----></h1>  <div class="theme-vdoing-content content__default"><h1 id="文件上传与下载和登录"><a href="#文件上传与下载和登录" class="header-anchor">#</a> 文件上传与下载和登录</h1> <h2 id="一、今天学习内容与目标"><a href="#一、今天学习内容与目标" class="header-anchor">#</a> 一、今天学习内容与目标</h2> <ul><li>掌握 Servlet 3.0 文件上传基本使用</li> <li>能够实现文件下载</li> <li>掌握登录的逻辑思想以及代码实现</li> <li>了解登录实现的完善过程中涉及到的问题</li> <li>掌握登录实现的最终版本</li> <li>掌握三层架构思想</li> <li>了解用户头像的实现</li></ul> <h2 id="二、文件上传"><a href="#二、文件上传" class="header-anchor">#</a> 二、文件上传</h2> <p>文件上传: 将用户本地磁盘中的文件提交保存到服务器中的磁盘上。</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20200517232527619.png" alt="image-20200517232527619"></p> <h3 id="_2-1-项目准备"><a href="#_2-1-项目准备" class="header-anchor">#</a> 2.1 项目准备</h3> <p>搭建一个新 Web 项目，名为 fileupload-download</p> <h3 id="_2-2-编写-register-jsp"><a href="#_2-2-编写-register-jsp" class="header-anchor">#</a> 2.2 编写 register.jsp</h3> <p>编写一个上传的表单，但要求如下：</p> <ul><li>method 需要使用 post 提交，get 限制了数据大小。</li> <li>enctype 需使用 multipart/form-data，不然直接报错（需要二进制数据）。</li> <li>需要提供 file 控件。</li></ul> <div class="language-jsp line-numbers-mode"><pre class="language-text"><code>&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;注册&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action=&quot;/fileUpload&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
        &lt;p&gt;账号:&lt;input type=&quot;text&quot; name=&quot;username&quot;/&gt;&lt;/p&gt;
        &lt;p&gt;头像:&lt;input type=&quot;file&quot; name=&quot;headImg&quot;/&gt;&lt;/p&gt;
        &lt;input type=&quot;submit&quot; value=&quot;注册&quot;&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><h3 id="_2-3-编写-fileuploadservlet-java"><a href="#_2-3-编写-fileuploadservlet-java" class="header-anchor">#</a> 2.3 编写 FileUploadServlet.java</h3> <p>在此 Servlet 的 service 中查看上传文件请求的表单数据。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span></span>_01_upload<span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/fileUpload&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FileUploadServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token comment">// 二进制提交的数据，getParameter 方法无法获取到</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;username&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 以流方式获取</span>
        <span class="token class-name">Scanner</span> sc <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Scanner</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span><span class="token function">getInputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">while</span> <span class="token punctuation">(</span>sc<span class="token punctuation">.</span><span class="token function">hasNextLine</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>sc<span class="token punctuation">.</span><span class="token function">nextLine</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p><strong>注意</strong>：<code>enctype=&quot;multipart/form-data&quot;</code> 提交的数据，getParameter() 无法获取到。</p> <h3 id="_2-4-查看请求数据及问题"><a href="#_2-4-查看请求数据及问题" class="header-anchor">#</a> 2.4 查看请求数据及问题</h3> <p>浏览器查看提交的数据格式：</p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20200518002300121.png" alt="image-20200518002300121"></p> <p>如何解析出上传文件的内容？可以自己解析流来获取上传文件的内容，但这样太麻烦了，而文件上传又是项目中基本都需要的功能，所以会有人帮咱们解决。</p> <h3 id="_2-5-servlet-3-0-文件上传"><a href="#_2-5-servlet-3-0-文件上传" class="header-anchor">#</a> 2.5 Servlet 3.0 文件上传</h3> <p>此前，对于处理上传文件的操作一直是开发者比较头疼的问题，因为 Servlet 本身没有提供直接的支持，需要使用第三方框架来实现（Apache 的 FileUpload 组件），第三方框架使用起来也不简单。如今这些都成为了历史，Servlet 3.0 提供了文件上传操作功能，而且使用也非常简单。</p> <h4 id="_2-5-1-api"><a href="#_2-5-1-api" class="header-anchor">#</a> 2.5.1 API</h4> <p>HttpServletRequest 提供了两个方法用于从请求中解析上传的文件</p> <table><thead><tr><th>返回值</th> <th>方法</th> <th>作用</th></tr></thead> <tbody><tr><td>Part</td> <td>getPart(String name)</td> <td>用于获取请求中指定 name 的文件</td></tr> <tr><td>Collection</td> <td>getParts()</td> <td>获取请求中全部的文件</td></tr></tbody></table> <p>Part 中常用方法：</p> <table><thead><tr><th>返回值</th> <th>方法</th> <th>作用</th></tr></thead> <tbody><tr><td>void</td> <td><strong>write(String fileName)</strong></td> <td>直接把接收到的文件保存到磁盘中</td></tr> <tr><td>void</td> <td>getContentType()</td> <td>获取文件的类型 MIME</td></tr> <tr><td>String</td> <td>getHeader(String name)</td> <td>获取请求头信息</td></tr> <tr><td>long</td> <td>getSize()</td> <td>获取文件的大小</td></tr></tbody></table> <p>只需要给 Servlet 贴一个标签 <code>@MultipartConfig</code> 然后使用 <code>getPart()</code> 获取请求中指定 name 的文件到 Part 对象中,再使用 write 方法把文件保存到指定目录就 ok 了.</p> <h4 id="_2-5-2-代码示例"><a href="#_2-5-2-代码示例" class="header-anchor">#</a> 2.5.2 代码示例</h4> <p>修改 FileUploadServlet 的 service 方法，使用 Servlet 3.0 上传 API 完成文件上传需求。只需要给 Servlet 贴一个标签 <code>@MultipartConfig</code> 然后使用请求对象的 <code>getPart()</code> 方法，指定上传控件的 name 的值，就可以获取到 Part 对象，再使用其 write 方法把数据写到指定文件就 ok 了。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span></span>_01_upload<span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/fileUpload&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@MultipartConfig</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FileUploadServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token comment">// 普通控件数据还是使用 getParameter 方法来获取</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">&quot;username:&quot;</span> <span class="token operator">+</span> req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;username&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 文件控件数据获取</span>
        <span class="token class-name">Part</span> part <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getPart</span><span class="token punctuation">(</span><span class="token string">&quot;headImg&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 保存到磁盘上</span>
        part<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token string">&quot;D:/headImg.png&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><h3 id="_2-6-文件上传细节"><a href="#_2-6-文件上传细节" class="header-anchor">#</a> 2.6 文件上传细节</h3> <h4 id="_2-6-1-获取上传文件名"><a href="#_2-6-1-获取上传文件名" class="header-anchor">#</a> 2.6.1 获取上传文件名</h4> <p>以前是拷贝文件（自传自存），知道文件类型；现在是用户传，程序接收，接收到文件时，涉及保存到磁盘使用什么文件名以及文件类型的问题，所以需要先获取到文件名及文件类型。可使用 Part API 获取：</p> <table><thead><tr><th>返回值</th> <th>方法</th> <th>作用</th></tr></thead> <tbody><tr><td>String</td> <td>getHeader(&quot;content-disposition&quot;)</td> <td>Tocmat 8.0 之前使用通过请求头获取文件名，需截取字符串</td></tr> <tr><td>String</td> <td>getSubmittedFileName()</td> <td>Tomcat8.0 之后提供的直接获取文件名方式</td></tr></tbody></table> <p>代码示例：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span></span>_01_upload<span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/fileUpload&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@MultipartConfig</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FileUploadServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token comment">// 文件控件数据获取</span>
        <span class="token class-name">Part</span> part <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getPart</span><span class="token punctuation">(</span><span class="token string">&quot;headImg&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 保存到磁盘上</span>
        part<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token string">&quot;D:/&quot;</span> <span class="token operator">+</span> part<span class="token punctuation">.</span><span class="token function">getSubmittedFileName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><h4 id="_2-6-2-文件名相同覆盖现有文件-掌握"><a href="#_2-6-2-文件名相同覆盖现有文件-掌握" class="header-anchor">#</a> 2.6.2 文件名相同覆盖现有文件(掌握)</h4> <p>若上传得文件名相同会导致覆盖服务器之前已上传的的文件，咱们的解决方法就是自己给文件起一个唯一的名称，确保不被覆盖，这里我们使用的是 UUID。</p> <p>代码示例：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span></span>_01_upload<span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/fileUpload&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@MultipartConfig</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FileUploadServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token comment">// 文件控件数据获取</span>
        <span class="token class-name">Part</span> part <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getPart</span><span class="token punctuation">(</span><span class="token string">&quot;headImg&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 获取上传文件名</span>
        <span class="token class-name">String</span> realFileName <span class="token operator">=</span> part<span class="token punctuation">.</span><span class="token function">getSubmittedFileName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 获取上传文件扩展名</span>
        <span class="token class-name">String</span> ext <span class="token operator">=</span> realFileName<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span>realFileName<span class="token punctuation">.</span><span class="token function">lastIndexOf</span><span class="token punctuation">(</span><span class="token string">&quot;.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 生成唯一字符串拼接文件名</span>
        <span class="token class-name">String</span> fileName <span class="token operator">=</span> <span class="token constant">UUID</span><span class="token punctuation">.</span><span class="token function">randomUUID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> ext<span class="token punctuation">;</span>
        <span class="token comment">// 保存到磁盘上</span>
        part<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token string">&quot;D:/&quot;</span> <span class="token operator">+</span> fileName<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><h4 id="_2-6-3-文件保存位置问题"><a href="#_2-6-3-文件保存位置问题" class="header-anchor">#</a> 2.6.3 文件保存位置问题</h4> <p>文件在磁盘某个位置，不在项目下，无法使用 HTTP 协议访问，所以要把用户上传的文件存放到项目中才可通过 HTTP 协议来访问，且保存的位置路径不可以写绝对路径，那么怎么办？可以通过 ServletContext 对象的 getRealPath(&quot;项目中保存上传文件的文件夹的相对路径&quot;) 来获取其的绝对路径。</p> <p><strong>在项目的 web 目录下新建一个名为 upload 文件夹</strong>，修改 UploadServlet.java 的代码如下：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span></span>_01_upload<span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/fileUpload&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@MultipartConfig</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FileUploadServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token comment">// 文件控件数据获取</span>
        <span class="token class-name">Part</span> part <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getPart</span><span class="token punctuation">(</span><span class="token string">&quot;headImg&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 获取上传文件名</span>
        <span class="token class-name">String</span> realFileName <span class="token operator">=</span> part<span class="token punctuation">.</span><span class="token function">getSubmittedFileName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 获取上传文件扩展名</span>
        <span class="token class-name">String</span> ext <span class="token operator">=</span> realFileName<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span>realFileName<span class="token punctuation">.</span><span class="token function">lastIndexOf</span><span class="token punctuation">(</span><span class="token string">&quot;.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 生成唯一字符串拼接文件名</span>
        <span class="token class-name">String</span> fileName <span class="token operator">=</span> <span class="token constant">UUID</span><span class="token punctuation">.</span><span class="token function">randomUUID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> ext<span class="token punctuation">;</span>
        <span class="token comment">// 获取项目下的 upload 目录的绝对路径，拼接成文件的保存路径</span>
        <span class="token class-name">String</span> realPath <span class="token operator">=</span> <span class="token function">getServletContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getRealPath</span><span class="token punctuation">(</span><span class="token string">&quot;/upload&quot;</span><span class="token punctuation">)</span> <span class="token operator">+</span><span class="token string">&quot;/&quot;</span><span class="token operator">+</span> fileName<span class="token punctuation">;</span>
        <span class="token comment">// 保存到磁盘上</span>
        part<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>realPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><h4 id="_2-6-4-无法获取项目下的-upload-目录"><a href="#_2-6-4-无法获取项目下的-upload-目录" class="header-anchor">#</a> 2.6.4 无法获取项目下的 upload 目录</h4> <p>以上方式没什么效果，原因是 IDEA 工具使用 <strong>打包 web 项目（war）</strong> 的方式来部署，所以位置有偏差，需要还原 Web 项目的原本目录结构，以及调整部署方式。调整步骤如下：</p> <ul><li>WEB-INF 下 创建 classes 目录，用于存放 class 文件</li> <li>修改项目 class 文件输出位置到 /WEB-INF/class 中（File -&gt; Project Structure）
<img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20200518071534102.png" alt="image-20200518071534102"></li> <li>调整项目部署方式为 External Source
<img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20200518071756074.png" alt="image-20200518071756074"></li></ul> <p>以上操作之后可以获取到项目下的 upload 目录了，但是之前的重新部署无效了，往后可使用编译类的方式来代替重新部署。
<img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20200518072255076.png" alt="image-20200518072255076"></p> <h3 id="_2-7-文件类型约束问题-掌握"><a href="#_2-7-文件类型约束问题-掌握" class="header-anchor">#</a> 2.7 文件类型约束问题(掌握)</h3> <p>限制用户恶意上传文件，比如要让用户上传头像，而用户却上传一个非图片文件，比如 JSP 文件。</p> <h4 id="_2-7-1-修改-uploadservlet-java"><a href="#_2-7-1-修改-uploadservlet-java" class="header-anchor">#</a> 2.7.1 修改 UploadServlet.java</h4> <p>加入判断上传文件类型的代码。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span></span>_01_upload<span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/fileUpload&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@MultipartConfig</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FileUploadServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token comment">// 文件控件数据获取</span>
        <span class="token class-name">Part</span> part <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getPart</span><span class="token punctuation">(</span><span class="token string">&quot;headImg&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 判断上传的文件类型合法不</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>part<span class="token punctuation">.</span><span class="token function">getContentType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">startsWith</span><span class="token punctuation">(</span><span class="token string">&quot;image/&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            req<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;errorMsg&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;请上传图片&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            req<span class="token punctuation">.</span><span class="token function">getRequestDispatcher</span><span class="token punctuation">(</span><span class="token string">&quot;/register.jsp&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forward</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token class-name">String</span> realFileName <span class="token operator">=</span> part<span class="token punctuation">.</span><span class="token function">getSubmittedFileName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 获取文件扩展名</span>
        <span class="token class-name">String</span> ext <span class="token operator">=</span> realFileName<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span>realFileName<span class="token punctuation">.</span><span class="token function">lastIndexOf</span><span class="token punctuation">(</span><span class="token string">&quot;.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 生成唯一字符串拼接文件名</span>
        <span class="token class-name">String</span> fileName <span class="token operator">=</span> <span class="token constant">UUID</span><span class="token punctuation">.</span><span class="token function">randomUUID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> ext<span class="token punctuation">;</span>
        <span class="token comment">// 获取项目下的 upload 目录的绝对路径，拼接成文件的保存路径</span>
        <span class="token class-name">String</span> realPath <span class="token operator">=</span> <span class="token function">getServletContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getRealPath</span><span class="token punctuation">(</span><span class="token string">&quot;/upload&quot;</span><span class="token punctuation">)</span> <span class="token operator">+</span><span class="token string">&quot;/&quot;</span><span class="token operator">+</span> fileName<span class="token punctuation">;</span>
        <span class="token comment">// 保存到磁盘上</span>
        part<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>realPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><h4 id="_2-7-2-修改-register-jsp"><a href="#_2-7-2-修改-register-jsp" class="header-anchor">#</a> 2.7.2 修改 register.jsp</h4> <p>显示上传文件类型错误的提示给用户。</p> <div class="language-jsp line-numbers-mode"><pre class="language-text"><code>&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;注册&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;span style=&quot;color: red&quot;&gt;${errorMsg}&lt;/span&gt;&lt;br/&gt;
    &lt;form action=&quot;/fileUpload&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
        &lt;p&gt;账号:&lt;input type=&quot;text&quot; name=&quot;username&quot;/&gt;&lt;/p&gt;
        &lt;p&gt;头像:&lt;input type=&quot;file&quot; name=&quot;headImg&quot;/&gt;&lt;/p&gt;
        &lt;input type=&quot;submit&quot; value=&quot;注册&quot;&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><h3 id="_2-8-文件大小约束问题"><a href="#_2-8-文件大小约束问题" class="header-anchor">#</a> 2.8 文件大小约束问题</h3> <p>文件上传限制大小可提高服务器硬盘的使用率，防止用户恶意上传文件造成服务器磁盘资源紧张。可以通过设置 @MutipartConfig 的属性做限制，其属性如下：</p> <ul><li><p>maxFileSize：单个上传文件大小限制，单位：bytes</p></li> <li><p>maxRequestSize：限制请求中数据的大小，单位：bytes</p></li></ul> <h4 id="_2-8-1-修改-register-jsp"><a href="#_2-8-1-修改-register-jsp" class="header-anchor">#</a> 2.8.1 修改 register.jsp</h4> <p>再提供一个上传文件的 input 元素。</p> <div class="language-jsp line-numbers-mode"><pre class="language-text"><code>&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;注册&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;span style=&quot;color: red&quot;&gt;${errorMsg}&lt;/span&gt;&lt;br/&gt;
    &lt;form action=&quot;/fileUpload&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
        &lt;p&gt;账号:&lt;input type=&quot;text&quot; name=&quot;username&quot;/&gt;&lt;/p&gt;
        &lt;p&gt;头像1:&lt;input type=&quot;file&quot; name=&quot;headImg&quot;/&gt;&lt;/p&gt;
        &lt;p&gt;头像2:&lt;input type=&quot;file&quot; name=&quot;headImg2&quot;/&gt;&lt;/p&gt;
        &lt;input type=&quot;submit&quot; value=&quot;注册&quot;&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><h4 id="_2-8-2-修改-fileuploadservlet-java"><a href="#_2-8-2-修改-fileuploadservlet-java" class="header-anchor">#</a> 2.8.2 修改 FileUploadServlet.java</h4> <p>使用 @MutipartConfig 注解限制上传文件的大小。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span></span>_01_upload<span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/fileUpload&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@MultipartConfig</span><span class="token punctuation">(</span>maxFileSize <span class="token operator">=</span> <span class="token number">80000</span><span class="token punctuation">,</span> maxRequestSize <span class="token operator">=</span> <span class="token number">140000</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FileUploadServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        req<span class="token punctuation">.</span><span class="token function">setCharacterEncoding</span><span class="token punctuation">(</span><span class="token string">&quot;UTF-8&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            <span class="token class-name">Collection</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Part</span><span class="token punctuation">&gt;</span></span> parts <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getParts</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">Part</span> part <span class="token operator">:</span> parts<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token class-name">String</span> contentType <span class="token operator">=</span> part<span class="token punctuation">.</span><span class="token function">getContentType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token comment">// 判断是否是文件控件</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>contentType <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// input 类型是 file</span>
                    <span class="token comment">// 判断上传的文件类型是否合法</span>
                    <span class="token keyword">if</span><span class="token punctuation">(</span>contentType<span class="token punctuation">.</span><span class="token function">startsWith</span><span class="token punctuation">(</span><span class="token string">&quot;image/&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
                        <span class="token comment">// 获取上传文件名</span>
                        <span class="token class-name">String</span> realFileName <span class="token operator">=</span> part<span class="token punctuation">.</span><span class="token function">getSubmittedFileName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token comment">// 获取文件扩展名</span>
                        <span class="token class-name">String</span> ext <span class="token operator">=</span> realFileName<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span>realFileName<span class="token punctuation">.</span><span class="token function">lastIndexOf</span><span class="token punctuation">(</span><span class="token string">&quot;.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token comment">// 生成唯一字符串拼接文件名</span>
                        <span class="token class-name">String</span> fileName <span class="token operator">=</span> <span class="token constant">UUID</span><span class="token punctuation">.</span><span class="token function">randomUUID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> ext<span class="token punctuation">;</span>
                        <span class="token comment">// 获取项目下的 upload 目录的绝对路径，拼接成文件的保存路径</span>
                        <span class="token class-name">String</span> baseDir <span class="token operator">=</span> <span class="token function">getServletContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getRealPath</span><span class="token punctuation">(</span><span class="token string">&quot;/upload/&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token comment">// 保存到磁盘上</span>
                        part<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>baseDir <span class="token operator">+</span> realPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token punctuation">}</span>
                    <span class="token comment">// 非图片文件不做任何处理</span>
                <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// input 类型非 file</span>
                    <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span>part<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            req<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;errorMsg&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;文件太大了&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            req<span class="token punctuation">.</span><span class="token function">getRequestDispatcher</span><span class="token punctuation">(</span><span class="token string">&quot;/register.jsp&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forward</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br></div></div><p><strong>拓展</strong>：抽取文件上传工具方法。</p> <h2 id="三、文件下载"><a href="#三、文件下载" class="header-anchor">#</a> 三、文件下载</h2> <p>将服务器中的资源下载保存到用户电脑中。</p> <h3 id="_3-1-文件下载简单实现"><a href="#_3-1-文件下载简单实现" class="header-anchor">#</a> 3.1 文件下载简单实现</h3> <h4 id="_3-1-1-在项目提供下载资源"><a href="#_3-1-1-在项目提供下载资源" class="header-anchor">#</a> 3.1.1 在项目提供下载资源</h4> <p>在 web 下新建 download 目录，里面提供两个资源 dog.rar 和 猫.rar。</p> <h4 id="_3-1-2-编写-download-jsp"><a href="#_3-1-2-编写-download-jsp" class="header-anchor">#</a> 3.1.2 编写 download.jsp</h4> <p>提供两个下载链接。</p> <div class="language-jsp line-numbers-mode"><pre class="language-text"><code>&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;下载&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h3&gt;文件下载&lt;/h3&gt;
    &lt;a href=&quot;/download/dog.rar&quot;&gt;dog.rar&lt;/a&gt;&lt;br/&gt;
    &lt;a href=&quot;/download/猫.rar&quot;&gt;猫.rar&lt;/a&gt;&lt;br/&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>效果如下：
<img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20200518074701185.png" alt="image-20200518074701185"></p> <h3 id="_3-2-文件下载限制-掌握"><a href="#_3-2-文件下载限制-掌握" class="header-anchor">#</a> 3.2 文件下载限制(掌握)</h3> <p>下载功能已经实现，但是文件放在 WEB-INF 外面不安全，用户只需要拿到下载的超链接都能够下载，实际开发中，我们的文件通常需要用户有一定的权限才能下载，所以文件应该放在 WEB-INF 下，这样的话，用户就不可以直接访问到了，须请求到交由 Servlet 来处理，我们就可以在其 service 方法中编写下载限制操作。</p> <h4 id="_3-2-1-移动下载资源到-web-inf-下"><a href="#_3-2-1-移动下载资源到-web-inf-下" class="header-anchor">#</a> 3.2.1 移动下载资源到 WEB-INF 下</h4> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20200518074717629.png" alt="image-20200518074717629"><br></p> <h4 id="_3-2-2-修改-download-jsp"><a href="#_3-2-2-修改-download-jsp" class="header-anchor">#</a> 3.2.2 修改 download.jsp</h4> <p>修改下载资源的链接地址。</p> <div class="language-jsp line-numbers-mode"><pre class="language-text"><code>&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;下载&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h3&gt;文件下载&lt;/h3&gt;
    &lt;a href=&quot;/download?fileName=dog.rar&quot;&gt;dog.rar&lt;/a&gt;&lt;br/&gt;
    &lt;a href=&quot;/download?fileName=猫.rar&quot;&gt;猫.rar&lt;/a&gt;&lt;br/&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><h4 id="_3-2-3-编写-downloadservlet-java"><a href="#_3-2-3-编写-downloadservlet-java" class="header-anchor">#</a> 3.2.3 编写 DownloadServlet.java</h4> <p>根据请求传递文件名参数获取对应文件响应给浏览器。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span></span>_01_upload<span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/download&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DownloadServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token comment">// 获取用户要下载的文件名称</span>
        <span class="token class-name">String</span> fileName <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;fileName&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 获取文件所在根路径</span>
        <span class="token class-name">String</span> realPath <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getServletContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getRealPath</span><span class="token punctuation">(</span><span class="token string">&quot;/WEB-INF/download/&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 使用工具类 Files 的 copy 方法获取文件输入流，响应回浏览器</span>
        <span class="token class-name">Files</span><span class="token punctuation">.</span><span class="token function">copy</span><span class="token punctuation">(</span><span class="token class-name">Paths</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>realPath<span class="token punctuation">,</span> fileName<span class="token punctuation">)</span><span class="token punctuation">,</span> resp<span class="token punctuation">.</span><span class="token function">getOutputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><h3 id="_3-3-下载文件名称问题-能使用即可"><a href="#_3-3-下载文件名称问题-能使用即可" class="header-anchor">#</a> 3.3 下载文件名称问题（能使用即可）</h3> <p>默认情况下，Tomcat 服务器未告知浏览器文件的名称，所以需要手动设置响应头来告知浏览器文件名称，方法如下：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">// 无需记，知道需要设置即可</span>
<span class="token comment">// 给浏览器一个推荐名称</span>
resp<span class="token punctuation">.</span><span class="token function">setHeader</span><span class="token punctuation">(</span><span class="token string">&quot;Content-Disposition&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;attachment;filename=文件名称&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>处理中文件名称的问题</p> <ul><li>IE 使用 URL 编码方式：URLEncoder.encode(fileName, &quot;UTF-8&quot;)</li> <li>非 IE使用 ISO-8859-1 编码：new String (fileName.getBytes(&quot;UTF-8&quot;), &quot;ISO-8859-1&quot;)</li></ul> <p>修改 DownloadServlet.java 代码如下：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span></span>_01_upload<span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/download&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DownloadServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token comment">// 获取用户要下载的文件名称</span>
        <span class="token class-name">String</span> fileName <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;fileName&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        
        <span class="token comment">// 获取浏览器类型</span>
        <span class="token class-name">String</span> header <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token string">&quot;User-Agent&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 根据浏览器类型设置文件下载的名称</span>
        <span class="token class-name">String</span> name <span class="token operator">=</span> <span class="token punctuation">(</span>header<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">&quot;MSIE&quot;</span><span class="token punctuation">)</span> <span class="token operator">||</span> header<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">&quot;Trident&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span> 
            			<span class="token operator">?</span>  <span class="token class-name">URLEncoder</span><span class="token punctuation">.</span><span class="token function">encode</span><span class="token punctuation">(</span>fileName<span class="token punctuation">,</span> <span class="token string">&quot;UTF-8&quot;</span><span class="token punctuation">)</span> 
            			<span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span>fileName<span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token string">&quot;UTF-8&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">&quot;ISO-8859-1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 设置下载文件名</span>
        resp<span class="token punctuation">.</span><span class="token function">setHeader</span><span class="token punctuation">(</span><span class="token string">&quot;Content-Disposition&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;attachment;filename=&quot;</span> <span class="token operator">+</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span>
        
        <span class="token comment">// 获取文件所在根路径</span>
        <span class="token class-name">String</span> realPath <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getServletContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getRealPath</span><span class="token punctuation">(</span><span class="token string">&quot;/WEB-INF/download/&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 使用工具类 Files 的 copy 方法获取文件输入流，响应回浏览器</span>
        <span class="token class-name">Files</span><span class="token punctuation">.</span><span class="token function">copy</span><span class="token punctuation">(</span><span class="token class-name">Paths</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>realPath<span class="token punctuation">,</span> fileName<span class="token punctuation">)</span><span class="token punctuation">,</span> resp<span class="token punctuation">.</span><span class="token function">getOutputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><h2 id="四、登录实现-掌握"><a href="#四、登录实现-掌握" class="header-anchor">#</a> 四、登录实现(掌握)</h2> <h3 id="_4-1-为什么做登录"><a href="#_4-1-为什么做登录" class="header-anchor">#</a> 4.1 为什么做登录</h3> <p>服务器资源给合理的人访问，在这里只有登录的用户才可以访问，比如只有登录的用户就可以访问产品进行CRUD。</p> <h3 id="_4-2-分析登录流程"><a href="#_4-2-分析登录流程" class="header-anchor">#</a> 4.2 分析登录流程</h3> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20200518151100135.png" alt="image-20200518151100135"></p> <h3 id="_4-3-登录实现"><a href="#_4-3-登录实现" class="header-anchor">#</a> 4.3 登录实现</h3> <h4 id="_4-3-1-项目准备及新建-user-表"><a href="#_4-3-1-项目准备及新建-user-表" class="header-anchor">#</a> 4.3.1 项目准备及新建 user 表</h4> <p>打开之前 Web CRUD 项目，在其对应的库中新建 user 表，并造一条数据，表结构如下：</p> <div class="language-sql line-numbers-mode"><pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token keyword">TABLE</span> <span class="token identifier"><span class="token punctuation">`</span>user<span class="token punctuation">`</span></span> <span class="token punctuation">(</span>
  <span class="token identifier"><span class="token punctuation">`</span>id<span class="token punctuation">`</span></span> <span class="token keyword">bigint</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span> <span class="token keyword">PRIMARY</span> <span class="token keyword">KEY</span> <span class="token keyword">AUTO_INCREMENT</span><span class="token punctuation">,</span>
  <span class="token identifier"><span class="token punctuation">`</span>username<span class="token punctuation">`</span></span> <span class="token keyword">varchar</span><span class="token punctuation">(</span><span class="token number">255</span><span class="token punctuation">)</span> <span class="token keyword">DEFAULT</span> <span class="token boolean">NULL</span><span class="token punctuation">,</span>
  <span class="token identifier"><span class="token punctuation">`</span>password<span class="token punctuation">`</span></span> <span class="token keyword">varchar</span><span class="token punctuation">(</span><span class="token number">255</span><span class="token punctuation">)</span> <span class="token keyword">DEFAULT</span> <span class="token boolean">NULL</span>
<span class="token punctuation">)</span> <span class="token keyword">ENGINE</span><span class="token operator">=</span><span class="token keyword">InnoDB</span> <span class="token keyword">DEFAULT</span> <span class="token keyword">CHARSET</span><span class="token operator">=</span>utf8<span class="token punctuation">;</span>

<span class="token keyword">INSERT</span> <span class="token keyword">INTO</span> <span class="token keyword">user</span><span class="token punctuation">(</span>username<span class="token punctuation">,</span> password<span class="token punctuation">)</span> <span class="token keyword">VALUES</span><span class="token punctuation">(</span><span class="token string">'xiaolang'</span><span class="token punctuation">,</span> <span class="token string">'123456'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h4 id="_4-3-2-编写-user-java"><a href="#_4-3-2-编写-user-java" class="header-anchor">#</a> 4.3.2 编写 User.java</h4> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>domain</span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@Setter</span>
<span class="token annotation punctuation">@Getter</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token class-name">Long</span> id<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> username<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> password<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><h4 id="_4-3-3-编写-usermapper-xml"><a href="#_4-3-3-编写-usermapper-xml" class="header-anchor">#</a> 4.3.3 编写 UserMapper.xml</h4> <p>在 mapper 包下新建 UserMapper.xml，文件内容如下：</p> <div class="language-xml line-numbers-mode"><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>checkUser<span class="token punctuation">&quot;</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>cn.wolfcode.domain.User<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    SELECT * FROM user WHERE username = #{username} AND password = #{password}
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>select</span><span class="token punctuation">&gt;</span></span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p><strong>记得在 mybatis-config.xml 关联。</strong></p> <h4 id="_4-3-4-编写-iuserdao-java-和-userdaoimpl-java"><a href="#_4-3-4-编写-iuserdao-java-和-userdaoimpl-java" class="header-anchor">#</a> 4.3.4 编写 IUserDAO.java 和 UserDAOImpl.java</h4> <p>里面提供根据用户名和密码查询用户的方法。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>dao</span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IUserDAO</span> <span class="token punctuation">{</span>
    <span class="token class-name">User</span> <span class="token function">checkUser</span><span class="token punctuation">(</span><span class="token class-name">User</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>dao<span class="token punctuation">.</span>impl</span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserDAOImpl</span> <span class="token keyword">implements</span> <span class="token class-name">IUserDAO</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">User</span> <span class="token function">checkUser</span><span class="token punctuation">(</span><span class="token class-name">User</span> user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SqlSession</span> session <span class="token operator">=</span> <span class="token class-name">MyBatisUtil</span><span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">User</span> u <span class="token operator">=</span> session<span class="token punctuation">.</span><span class="token function">selectOne</span><span class="token punctuation">(</span><span class="token string">&quot;cn.wolfcode.mapper.UserMapper.checkUser&quot;</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
        session<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> u<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><h4 id="_4-3-5-编写-loginservlet-java"><a href="#_4-3-5-编写-loginservlet-java" class="header-anchor">#</a> 4.3.5 编写 LoginServlet.java</h4> <p>处理登录请求，对登录成功或失败进行响应。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet</span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/login&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">LoginServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>
    
    <span class="token keyword">private</span> <span class="token class-name">IUserDAO</span> userDAO <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserDAOImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        req<span class="token punctuation">.</span><span class="token function">setCharacterEncoding</span><span class="token punctuation">(</span><span class="token string">&quot;UTF-8&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 接受请求参数，封装成对象</span>
        <span class="token class-name">User</span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        user<span class="token punctuation">.</span><span class="token function">setUsername</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;username&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        user<span class="token punctuation">.</span><span class="token function">setPassword</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;password&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 调用业务方法来处理登录请求</span>
        <span class="token class-name">User</span> u <span class="token operator">=</span> userDAO<span class="token punctuation">.</span><span class="token function">checkUser</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>u <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token comment">// 通知用户账号或密码错误</span>
            req<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;errorMsg&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;账号或密码错误&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            req<span class="token punctuation">.</span><span class="token function">getRequestDispatcher</span><span class="token punctuation">(</span><span class="token string">&quot;/login.jsp&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forward</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token comment">// 登录成功，重定向产品列表页面</span>
        resp<span class="token punctuation">.</span><span class="token function">sendRedirect</span><span class="token punctuation">(</span><span class="token string">&quot;/product&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><h4 id="_4-3-6-编写-login-jsp"><a href="#_4-3-6-编写-login-jsp" class="header-anchor">#</a> 4.3.6 编写 login.jsp</h4> <p>在 web 目录新建 login.jsp，文件内容如下：</p> <div class="language-jsp line-numbers-mode"><pre class="language-text"><code>&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;登录&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h3&gt;用户登录&lt;/h3&gt;
    ${errorMsg}
    &lt;form action=&quot;/login&quot; method=&quot;post&quot;&gt;
        &lt;p&gt;账号: &lt;input type=&quot;text&quot; name=&quot;username&quot;&gt;&lt;/p&gt;
        &lt;p&gt;密码: &lt;input type=&quot;text&quot; name=&quot;password&quot;&gt;&lt;/p&gt;
        &lt;input type=&quot;submit&quot; value=&quot;登录&quot;&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><h3 id="_4-4-访问限制"><a href="#_4-4-访问限制" class="header-anchor">#</a> 4.4 访问限制</h3> <p>因为上面虽然把登录需求做完，但大家发现，若在浏览器地址中直接输入 localhost/product 访问依然是可以的。那么怎么解决这个问题呢？</p> <h4 id="_4-4-1-修改-loginservlet-java"><a href="#_4-4-1-修改-loginservlet-java" class="header-anchor">#</a> 4.4.1 修改 LoginServlet.java</h4> <p>当登录成功时往 Session 中存入一个标识，比如 User 对象，给其它需要登录才可以操作的资源做判断使用。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet</span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/login&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">LoginServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token class-name">IUserDAO</span> userDAO <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserDAOImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        req<span class="token punctuation">.</span><span class="token function">setCharacterEncoding</span><span class="token punctuation">(</span><span class="token string">&quot;UTF-8&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 接受请求参数，封装成对象</span>
        <span class="token class-name">User</span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        user<span class="token punctuation">.</span><span class="token function">setUsername</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;username&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        user<span class="token punctuation">.</span><span class="token function">setPassword</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;password&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 调用业务方法来处理登录请求</span>
        <span class="token class-name">User</span> u <span class="token operator">=</span> userDAO<span class="token punctuation">.</span><span class="token function">checkUser</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>u <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token comment">// 通知用户账号或密码错误</span>
            req<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;errorMsg&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;账号或密码错误&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            req<span class="token punctuation">.</span><span class="token function">getRequestDispatcher</span><span class="token punctuation">(</span><span class="token string">&quot;/login.jsp&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forward</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// 登录成功时往 Session 中加入一个登录成功的标识</span>
        req<span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;USER_IN_SESSION&quot;</span><span class="token punctuation">,</span> u<span class="token punctuation">)</span><span class="token punctuation">;</span>
        
        <span class="token comment">// 重定向产品列表页面</span>
        resp<span class="token punctuation">.</span><span class="token function">sendRedirect</span><span class="token punctuation">(</span><span class="token string">&quot;/product&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br></div></div><h4 id="_4-4-2-修改-productservlet-的-service-方法"><a href="#_4-4-2-修改-productservlet-的-service-方法" class="header-anchor">#</a> 4.4.2 修改 ProductServlet 的 service 方法</h4> <p>对产品 CRUD 的资源或者操作是需要登录才可以访问或操作，那么从 Session 中来获取登录的标识，获取到则有登录可以访问或操作；获取不到则没登录，没登录则跳转去登录页面。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
    req<span class="token punctuation">.</span><span class="token function">setCharacterEncoding</span><span class="token punctuation">(</span><span class="token string">&quot;UTF-8&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token comment">// 判断 Session 中是否有登录的标示，有则说明登录成功了，没有则说明没有登录</span>
    <span class="token class-name">Object</span> user <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;USER_IN_SESSION&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>user <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token comment">// 没有登录滚去登录</span>
        resp<span class="token punctuation">.</span><span class="token function">sendRedirect</span><span class="token punctuation">(</span><span class="token string">&quot;/login.jsp&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token class-name">String</span> cmd <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;cmd&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// 针对参数 cmd 值不同，分发到不同的方法去处理</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token string">&quot;delete&quot;</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token function">delete</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token string">&quot;input&quot;</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token function">input</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token string">&quot;saveOrUpdate&quot;</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token function">saveOrUpdate</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{</span>
        <span class="token function">list</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><h3 id="_4-5-登录实现异常提示"><a href="#_4-5-登录实现异常提示" class="header-anchor">#</a> 4.5 登录实现异常提示</h3> <p>若现在新增一个需求，登录时若用户名写错了，提示用户其输入的用户名错了；若是密码写错了，提示用户其输入的密码错了。</p> <h4 id="_4-5-1-修改-usermapper-xml"><a href="#_4-5-1-修改-usermapper-xml" class="header-anchor">#</a> 4.5.1 修改 UserMapper.xml</h4> <div class="language-xml line-numbers-mode"><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>checkByUsername<span class="token punctuation">&quot;</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>cn.wolfcode.domain.User<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    SELECT * FROM user WHERE username = #{username}
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>select</span><span class="token punctuation">&gt;</span></span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><h4 id="_4-5-2-修改-iuserdao-java-和-userdaoimpl-java"><a href="#_4-5-2-修改-iuserdao-java-和-userdaoimpl-java" class="header-anchor">#</a> 4.5.2 修改 IUserDAO.java 和 UserDAOImpl.java</h4> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>dao</span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IUserDAO</span> <span class="token punctuation">{</span>
    <span class="token class-name">User</span> <span class="token function">checkUser</span><span class="token punctuation">(</span><span class="token class-name">String</span> username<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>dao<span class="token punctuation">.</span>impl</span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserDAOImpl</span> <span class="token keyword">implements</span> <span class="token class-name">IUserDAO</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">User</span> <span class="token function">checkUser</span><span class="token punctuation">(</span><span class="token class-name">String</span> username<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SqlSession</span> session <span class="token operator">=</span> <span class="token class-name">MyBatisUtil</span><span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">User</span> u <span class="token operator">=</span> session<span class="token punctuation">.</span><span class="token function">selectOne</span><span class="token punctuation">(</span><span class="token string">&quot;cn.wolfcode.mapper.UserMapper.checkByUsername&quot;</span><span class="token punctuation">,</span> username<span class="token punctuation">)</span><span class="token punctuation">;</span>
        session<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> u<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><h4 id="_4-5-3-修改-loginservlet-java"><a href="#_4-5-3-修改-loginservlet-java" class="header-anchor">#</a> 4.5.3 修改 LoginServlet.java</h4> <p>登录时若用户名写错了，提示用户其输入的用户名错了；若是密码写错了，提示用户其收入的密码错了。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet</span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/login&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">LoginServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token class-name">IUserDAO</span> userDAO <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserDAOImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        req<span class="token punctuation">.</span><span class="token function">setCharacterEncoding</span><span class="token punctuation">(</span><span class="token string">&quot;UTF-8&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 接受请求参数</span>
        <span class="token class-name">User</span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> username <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;username&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> password <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;password&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        
        <span class="token comment">// 调用业务方法来处理登录请求</span>
        <span class="token class-name">User</span> u <span class="token operator">=</span> userDAO<span class="token punctuation">.</span><span class="token function">checkUser</span><span class="token punctuation">(</span>username<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 判断用户名是否正确</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>u <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            req<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;errorMsg&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;账号不存在&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            req<span class="token punctuation">.</span><span class="token function">getRequestDispatcher</span><span class="token punctuation">(</span><span class="token string">&quot;/login.jsp&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forward</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token comment">// 判断密码是否正确</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>u<span class="token punctuation">.</span><span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>password<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            req<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;errorMsg&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;密码错误&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            req<span class="token punctuation">.</span><span class="token function">getRequestDispatcher</span><span class="token punctuation">(</span><span class="token string">&quot;/login.jsp&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forward</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// 登录成功时往 Session 中加入一个登录成功的标识，给其它需要登录才可以操作的资源做判断使用</span>
        req<span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;USER_IN_SESSION&quot;</span><span class="token punctuation">,</span> u<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 重定向产品列表页面</span>
        resp<span class="token punctuation">.</span><span class="token function">sendRedirect</span><span class="token punctuation">(</span><span class="token string">&quot;/product&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br></div></div><h4 id="_4-5-4-存在的问题"><a href="#_4-5-4-存在的问题" class="header-anchor">#</a> 4.5.4 存在的问题</h4> <p>目前在 Servlet 中书写了逻辑的操作代码，这不属于 Servlet 的责职的，怎么办？解决方案：抽取 Servlet 的逻辑代码。</p> <h2 id="五、登录加入业务层-掌握"><a href="#五、登录加入业务层-掌握" class="header-anchor">#</a> 五、登录加入业务层(掌握)</h2> <h3 id="_5-1-三层架构介绍"><a href="#_5-1-三层架构介绍" class="header-anchor">#</a> 5.1 三层架构介绍</h3> <p>Web 开发中的最佳实践：分层开发模式（技术层面的&quot;分而治之&quot;）。三层架构(3-tier architecture)：通常意义上的三层架构就是将整个业务应用划分为：<strong>表现层、业务逻辑层、数据访问层</strong>。区分层次的目的即为了“高内聚低耦合”的思想。在软件体系架构设计中，分层式结构是最常见，也是最重要的一种结构。</p> <ul><li><strong>表现层</strong>（Predentation Layer）：MVC，负责处理与界面交互的相关操作。</li> <li><strong>业务层</strong>（Business Layer）：Service，负责复杂的业务逻辑计算和判断。</li> <li><strong>持久层</strong>（Persistent Layer）：DAO，负责将业务逻辑数据进行持久化存储。</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20200518084705988.png" alt="image-20200518084705988"></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20200518084700057.png" alt="image-20200518084700057"></p> <p><img src="https://cdn.jsdelivr.net/gh/langfeiyes/images-khub/image-20200518084714450.png" alt="image-20200518084714450"></p> <p><strong>分层好处</strong>：责任分离，各司其职，体现高内聚低耦合。</p> <h3 id="_5-2-业务层命名规范-掌握"><a href="#_5-2-业务层命名规范-掌握" class="header-anchor">#</a> 5.2 业务层命名规范(掌握)</h3> <ul><li><p>包名：</p> <ul><li>公司域名倒写.模块名.service：存放业务接口代码。</li> <li>公司域名倒写.模块名.service.impl：存放业务层接口的实现类。</li></ul></li> <li><p>类名：</p> <ul><li><p>IXxxService：业务层接口，Xxx 表示对应模型，比如操作 User 的就起名为 IUserService。</p></li> <li><p>XxxServiceImpl：业务层接口对应的实现类，比如操作 User 的就起名为 UserServiceImpl。</p></li> <li><p>XxxServiceTest：业务层实现的测试类。</p></li></ul></li></ul> <h3 id="_5-3-编写-iuserservice-java-和-userserviceimpl-java"><a href="#_5-3-编写-iuserservice-java-和-userserviceimpl-java" class="header-anchor">#</a> 5.3 编写 IUserService.java 和 UserServiceImpl.java</h3> <p>调用 DAO 对象的查询方法，若登录失败，通过抛出异常的方式，返回错误信息。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>service</span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IUserService</span> <span class="token punctuation">{</span>
    <span class="token class-name">User</span> <span class="token function">login</span><span class="token punctuation">(</span><span class="token class-name">String</span> username<span class="token punctuation">,</span> <span class="token class-name">String</span> password<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>service<span class="token punctuation">.</span>impl</span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserServiceImpl</span> <span class="token keyword">implements</span> <span class="token class-name">IUserService</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token class-name">IUserDAO</span> userDAO <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserDAOImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token class-name">User</span> <span class="token function">login</span><span class="token punctuation">(</span><span class="token class-name">String</span> username<span class="token punctuation">,</span> <span class="token class-name">String</span> password<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">User</span> user <span class="token operator">=</span> userDAO<span class="token punctuation">.</span><span class="token function">checkUser</span><span class="token punctuation">(</span>username<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 用户名错误</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>user <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">&quot;账号不存在&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token comment">// 密码错误</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>user<span class="token punctuation">.</span><span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>password<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span><span class="token punctuation">(</span><span class="token string">&quot;密码错误&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> user<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><h3 id="_5-4-修改-loginservlet-java"><a href="#_5-4-修改-loginservlet-java" class="header-anchor">#</a> 5.4 修改 LoginServlet.java</h3> <p>调用业务对象的业务方法。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet</span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/login&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">LoginServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token class-name">IUserService</span> userService <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserServiceImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        req<span class="token punctuation">.</span><span class="token function">setCharacterEncoding</span><span class="token punctuation">(</span><span class="token string">&quot;UTF-8&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 接受请求参数</span>
        <span class="token class-name">String</span> username <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;username&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> password <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getParameter</span><span class="token punctuation">(</span><span class="token string">&quot;password&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            <span class="token comment">// 调用业务方法来处理登录请求</span>
            <span class="token class-name">User</span> user <span class="token operator">=</span> userService<span class="token punctuation">.</span><span class="token function">login</span><span class="token punctuation">(</span>username<span class="token punctuation">,</span> password<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment">// 登录成功时往 Session 中加入一个登录成功的标识，给其它需要登录才可以操作的资源做判断使用</span>
            req<span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;USER_IN_SESSION&quot;</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment">// 控制跳转</span>
            resp<span class="token punctuation">.</span><span class="token function">sendRedirect</span><span class="token punctuation">(</span><span class="token string">&quot;/product&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment">// 有异常时表示登录失败，</span>
            e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            req<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;errorMsg&quot;</span><span class="token punctuation">,</span> e<span class="token punctuation">.</span><span class="token function">getMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            req<span class="token punctuation">.</span><span class="token function">getRequestDispatcher</span><span class="token punctuation">(</span><span class="token string">&quot;/login.jsp&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forward</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> resp<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div><h2 id="六、加入用户头像-拓展"><a href="#六、加入用户头像-拓展" class="header-anchor">#</a> 六、加入用户头像(拓展)</h2> <h3 id="_6-1-显示用户头像"><a href="#_6-1-显示用户头像" class="header-anchor">#</a> 6.1 显示用户头像</h3> <h4 id="_6-1-1-新建存放头像文件夹"><a href="#_6-1-1-新建存放头像文件夹" class="header-anchor">#</a> 6.1.1 新建存放头像文件夹</h4> <p>在项目中的 web 目录新建一个 headImg 文件夹，把一些头像图片放进去。</p> <h4 id="_6-1-2-修改-user-表"><a href="#_6-1-2-修改-user-表" class="header-anchor">#</a> 6.1.2 修改 user 表</h4> <p>给 user 表新增一个 headImg 字段，类型 varchar，用于记录用户头像图片路径。给现有用户数据的 headImg 字段设置好现有图片的路径。</p> <h4 id="_6-1-3-修改-user-java"><a href="#_6-1-3-修改-user-java" class="header-anchor">#</a> 6.1.3 修改 User.java</h4> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>domain</span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@Setter</span>
<span class="token annotation punctuation">@Getter</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token class-name">Long</span> id<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> username<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> password<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> headImg<span class="token punctuation">;</span> <span class="token comment">// 增加头像字段</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h4 id="_6-1-4-修-list-jsp"><a href="#_6-1-4-修-list-jsp" class="header-anchor">#</a> 6.1.4 修 list.jsp</h4> <p>在产品的 list.jsp 的添加 a 标签之前添加如下代码：</p> <div class="language-jsp line-numbers-mode"><pre class="language-text"><code>&lt;img src=&quot;${USER_IN_SESSION.headImg}&quot;/&gt;&lt;br/&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h3 id="_6-2-修改用户头像"><a href="#_6-2-修改用户头像" class="header-anchor">#</a> 6.2 修改用户头像</h3> <h4 id="_6-2-1-修改-list-jsp"><a href="#_6-2-1-修改-list-jsp" class="header-anchor">#</a> 6.2.1 修改 list.jsp</h4> <p>点击用户头像跳转修改头像的页面。</p> <div class="language-jsp line-numbers-mode"><pre class="language-text"><code>&lt;a href=&quot;/replaceImg.jsp&quot;&gt;&lt;img src=&quot;${USER_IN_SESSION.headImg}&quot; title=&quot;更换头像&quot;/&gt;&lt;/a&gt;&lt;br/&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h4 id="_6-2-2-编写-replaceimg-jsp"><a href="#_6-2-2-编写-replaceimg-jsp" class="header-anchor">#</a> 6.2.2 编写 replaceImg.jsp</h4> <p>在项目的 web 目录新建 replaceImg.jsp，编写一个上传头像的表单。</p> <div class="language-jsp line-numbers-mode"><pre class="language-text"><code>&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;头像修改&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action=&quot;/replaceImg&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
        更换头像：&lt;input type=&quot;file&quot; name=&quot;headImg&quot;&gt;
        &lt;input type=&quot;submit&quot; value=&quot;提交&quot;&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><h4 id="_6-2-3-编写-headimgservlet-java"><a href="#_6-2-3-编写-headimgservlet-java" class="header-anchor">#</a> 6.2.3 编写 HeadImgServlet.java</h4> <p>接受用户修改头像的请求并调用业务方法修改用户头像。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">cn<span class="token punctuation">.</span>wolfcode<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet</span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@WebServlet</span><span class="token punctuation">(</span><span class="token string">&quot;/replaceImg&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@MultipartConfig</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">HeadImgServlet</span> <span class="token keyword">extends</span> <span class="token class-name">HttpServlet</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token class-name">IUserService</span> userService <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserServiceImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> req<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> resp<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">ServletException</span><span class="token punctuation">,</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token comment">// 判断是否有登录，有则可以修改头像</span>
        <span class="token class-name">Object</span> obj <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;USER_IN_SESSION&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>obj <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            resp<span class="token punctuation">.</span><span class="token function">sendRedirect</span><span class="token punctuation">(</span><span class="token string">&quot;/login.jsp&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token comment">// 有登录，获取新上传的头像图片</span>
        <span class="token class-name">Part</span> part <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getPart</span><span class="token punctuation">(</span><span class="token string">&quot;headImg&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 获取上传文件名称</span>
        <span class="token class-name">String</span> fileName <span class="token operator">=</span> part<span class="token punctuation">.</span><span class="token function">getSubmittedFileName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 获取上传文件后缀名</span>
        <span class="token class-name">String</span> ext <span class="token operator">=</span> fileName<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span>fileName<span class="token punctuation">.</span><span class="token function">lastIndexOf</span><span class="token punctuation">(</span><span class="token string">&quot;.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 创建的文件名，需要存到数据库中的</span>
        <span class="token class-name">String</span> newFileName <span class="token operator">=</span>  <span class="token constant">UUID</span><span class="token punctuation">.</span><span class="token function">randomUUID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> ext<span class="token punctuation">;</span>
        <span class="token comment">// 获取图片存放的根路径</span>
        <span class="token class-name">String</span> baseDir <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">getServletContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getRealPath</span><span class="token punctuation">(</span><span class="token string">&quot;/headImg&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 上传的头像保存倒磁盘中</span>
        part<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>baseDir <span class="token operator">+</span> <span class="token string">&quot;/&quot;</span> <span class="token operator">+</span> newFileName<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token class-name">User</span> user <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">User</span><span class="token punctuation">)</span> obj<span class="token punctuation">;</span>
        user<span class="token punctuation">.</span><span class="token function">setHeadImg</span><span class="token punctuation">(</span><span class="token string">&quot;/headImg/&quot;</span> <span class="token operator">+</span> newFileName<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 调用业务方法来修改用户头像</span>
        userService<span class="token punctuation">.</span><span class="token function">updateHeadImg</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 控制跳转</span>
        resp<span class="token punctuation">.</span><span class="token function">sendRedirect</span><span class="token punctuation">(</span><span class="token string">&quot;/product&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br></div></div><h4 id="_6-2-4-修改-iuserservice-java-和-userserviceimpl-java"><a href="#_6-2-4-修改-iuserservice-java-和-userserviceimpl-java" class="header-anchor">#</a> 6.2.4 修改 IUserService.java 和 UserServiceImpl.java</h4> <p>提供修改用户头像的业务方法。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">void</span> <span class="token function">updateHeadImg</span><span class="token punctuation">(</span><span class="token class-name">User</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">updateHeadImg</span><span class="token punctuation">(</span><span class="token class-name">User</span> user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    userDAO<span class="token punctuation">.</span><span class="token function">updateHeadImg</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><h4 id="_6-2-5-修改-iuserdao-java-和-userdaoimpl-java"><a href="#_6-2-5-修改-iuserdao-java-和-userdaoimpl-java" class="header-anchor">#</a> 6.2.5 修改 IUserDAO.java 和 UserDAOImpl.java</h4> <p>提供修改用户头像的方法。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">void</span> <span class="token function">updateHeadImg</span><span class="token punctuation">(</span><span class="token class-name">User</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">updateHeadImg</span><span class="token punctuation">(</span><span class="token class-name">User</span> user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token class-name">SqlSession</span> session <span class="token operator">=</span> <span class="token class-name">MyBatisUtil</span><span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    session<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span><span class="token string">&quot;cn.wolfcode.mapper.UserMapper.updateHeadImg&quot;</span><span class="token punctuation">,</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
    session<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    session<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h4 id="_6-2-6-修改-usermapper-xml"><a href="#_6-2-6-修改-usermapper-xml" class="header-anchor">#</a> 6.2.6 修改 UserMapper.xml</h4> <div class="language-xml line-numbers-mode"><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>update</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>updateHeadImg<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    UPDATE user SET headImg = #{headImg} WHERE id = #{id}
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>update</span><span class="token punctuation">&gt;</span></span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><h2 id="七、小结也作业"><a href="#七、小结也作业" class="header-anchor">#</a> 七、小结也作业</h2> <h3 id="_7-1-小结"><a href="#_7-1-小结" class="header-anchor">#</a> 7.1 小结</h3> <ul><li>掌握 Servlet3.0 文件上传的基本操作</li> <li>注意文件上传,文件名,文件类型约束,位置要注意放到项目下,才可以通过 http 协议获取</li> <li>掌握文件下载的基本操作(Files.copy 方法)</li> <li>注意文件下载的推荐名称的设置(响应头设置以及名字的编码处理)</li> <li>掌握登录实现的其中一个版本</li> <li>掌握访问权限的限制(必须登录之后才能做 crud) -&gt; 登录成功把用户信息存入 session 对象中</li> <li>理解 三层架构有哪三层? 三层架构有什么作用? 每一层负责做什么事情?</li> <li>掌握业务层的实现(User 表加入了业务层)</li></ul> <h3 id="_7-2-作业"><a href="#_7-2-作业" class="header-anchor">#</a> 7.2 作业</h3> <ul><li>重点练习基于Servlet3.0 的文件上传的基本操作</li> <li>进行文件上传的细节操作（文件名的修改，文件类型的约束,文件位置调整（idea 输出路径修改和项目部署方式的修改：看着讲义来操作））</li> <li>重点练习文件下载的基本操作（页面+Servlet：1 获取文件名，2 获取目录，3 实现文件拷贝Files.copy()）</li> <li>重点练习登录功能的其中一种实现方式</li> <li>重点练习在登录功能上加入业务层</li> <li>拓展：加入用户头像</li></ul></div></div>  <div class="page-edit"><!----> <div class="tags"><a href="/tags/?tag=%E4%B8%8A%E4%BC%A0" title="标签">#上传</a><a href="/tags/?tag=%E4%B8%8B%E8%BD%BD" title="标签">#下载</a></div> <!----></div> <div class="page-nav-wapper"><div class="page-nav-centre-wrap"><a href="/pages/baec2f/" class="page-nav-centre page-nav-centre-prev"><div class="tooltip">Cookie与Session</div></a> <a href="/pages/f99e33/" class="page-nav-centre page-nav-centre-next"><div class="tooltip">项目实战-MIS系统</div></a></div> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/pages/baec2f/" class="prev">Cookie与Session</a></span> <span class="next"><a href="/pages/f99e33/">项目实战-MIS系统</a>→
      </span></p></div></div></div> <div class="article-list"><div class="article-title"><a href="/archives/" class="iconfont icon-bi">最近更新</a></div> <div class="article-wrapper"><dl><dd>01</dd> <dt><a href="/pages/0c07b2/"><div>
            IT杂货铺
            <!----></div></a> <span class="date">03-23</span></dt></dl><dl><dd>02</dd> <dt><a href="/pages/705b35/"><div>
            人事百问
            <!----></div></a> <span class="date">03-22</span></dt></dl><dl><dd>03</dd> <dt><a href="/pages/78eb56/"><div>
            MyBatis-Plus
            <!----></div></a> <span class="date">03-12</span></dt></dl> <dl><dd></dd> <dt><a href="/archives/" class="more">更多文章&gt;</a></dt></dl></div></div></main></div> <div class="footer"><div class="icons"><a href="mailto:langfeiyes@163.com" title="发邮件" target="_blank" class="iconfont icon-youjian"></a><a href="https://github.com/langfeiyes" title="GitHub" target="_blank" class="iconfont icon-github"></a><a href="https://music.163.com/#/playlist?id=755597173" title="听音乐" target="_blank" class="iconfont icon-erji"></a></div> 
  Theme by
  <a href="https://github.com/xugaoyi/vuepress-theme-vdoing" target="_blank" title="本站主题">Vdoing</a> 
    | Copyright © 2024-2024
    <span><a href="https://beian.miit.gov.cn/" target="_blank">粤ICP备18007927号-1</a></span></div> <div class="buttons"><div title="返回顶部" class="button blur go-to-top iconfont icon-fanhuidingbu" style="display:none;"></div> <div title="去评论" class="button blur go-to-comment iconfont icon-pinglun" style="display:none;"></div> <div title="主题模式" class="button blur theme-mode-but iconfont icon-zhuti"><ul class="select-box" style="display:none;"><li class="iconfont icon-zidong">
          跟随系统
        </li><li class="iconfont icon-rijianmoshi">
          浅色模式
        </li><li class="iconfont icon-yejianmoshi">
          深色模式
        </li><li class="iconfont icon-yuedu">
          阅读模式
        </li></ul></div></div> <!----> <!----> <!----></div><div class="global-ui"><div></div></div></div>
    <script src="/assets/js/app.a2a00aa5.js" defer></script><script src="/assets/js/2.256f807a.js" defer></script><script src="/assets/js/44.7c7cb8a9.js" defer></script>
  </body>
</html>
